#ifndef MESH_WIDGET_H
#define MESH_WIDGET_H

#include <QGLWidget>
#include <QTimer>
#include <boost/scoped_ptr.hpp>

#include <core/util/mesh.h>
#include <core/util/manipulator.h>

namespace widgets {

  class Mesh : public QGLWidget
  {
    Q_OBJECT

  public:
    Mesh(QWidget *parent = 0);
    ~Mesh();

    void AddMesh(const QString & Name_, IMesh *pMesh_);

    void RecalculateBounds();
    bool get_wireframe();
    const QGradientStops & GetStops() const;

  public slots:
    void set_pan(qreal x_pan, qreal y_pan);
    void set_rotation(qreal z_axis, qreal x_axis);
    void set_zoom(qreal zoom);
    void set_wireframe(bool wireframe);
    void toggle_wireframe();
    void SetStops(const QGradientStops & _Stops, qreal MinValue, qreal MaxValue, const QString & _Caption);
    
  signals:
    void OnElementPicked(IMesh::element_type, int);
    void OnElementPickedDouble(IMesh::element_type, int);

  protected:
    virtual void initializeGL();
    virtual void paintGL();
    virtual void resizeGL(int width, int height);
    virtual void mouseMoveEvent(QMouseEvent *p_event);
    virtual void mousePressEvent(QMouseEvent *p_event);
    virtual void mouseDoubleClickEvent(QMouseEvent *p_event);
    virtual void mouseReleaseEvent(QMouseEvent *p_event);
    virtual void wheelEvent(QWheelEvent *p_event);
    
    void PickElement(const QPoint &pt);
    
    static bool PtInTriangle(
        const QPointF &pt,
        const QPointF &t1,
        const QPointF &t2,
        const QPointF &t3
      );

  private: // methods
    void draw_gl_primitives(IMesh *pMesh, IMesh::element_type type, GLenum gl_mode) const;

  private: // fields
    QMap<QString, IMesh *> mMeshContainer;
    IMesh::vector bounds[2];

    boost::scoped_ptr<Manipulator> p_manipulator_;

    QPointF pan_;
    QPointF rotation_;
    qreal zoom_;
    bool wireframe_;

    IMesh::element_type selectedItemType;
    int                 selectedItemIndex;

    QString m_Caption;
    QGradientStops m_Stops;
    qreal m_StopMinValue;
    qreal m_StopMaxValue;

    GLdouble m_MatrixModel[16];
    GLdouble m_MatrixRotation[16];
    GLdouble m_MatrixRotationManipulator[16];
    GLdouble m_MatrixProjection[16];
    GLint    m_Viewport[4];
  };

} // namespace widgets {

#endif // MESH_WIDGET_H
